/*
 * @Author: czy
 * @Date: 2021-05-30 22:59:14
 * @LastEditTime: 2021-06-04 16:42:39
 */
#ifndef __CONTAINER_H_
#define __CONTAINER_H_

#include "string.h"

#define INIT_LENGTH 8
#define TRUE 1
#define FALSE 0

#define NOTINIT -1
#define UNKNOWN 0
#define POINTER 1
#define STRING 2
#define RAWDATA 3

struct INFO
{
    char typeinfo[16];
    char lengthinfo[8];
    int size1;
    int size2;
};

typedef struct
{
    struct INFO info;
    int length;
    int allocated;
    int size;
    int type;
    void **data;
    void (*resize)(void *vector);
    void (*append)(void *vector, ...);
    void *(*get)(void *vector, int index);
    int (*set)(void *vector, int index, ...);
    void *(*pop)(void *vector, void *value, ...);
    int (*insert)(void *vector, int index, ...);
    int (*remove)(void *vector, int index);
    void (*clear)(void *vector);
} Vector;

void vector_resize(void *vector);
void vector_append(void *vector, ...);
void *vector_pop(void *vector, void *value, ...);
int vector_insert(void *vector, int index, ...);
int vector_remove(void *vector, int index);
void *vector_get(void *vector, int index);
int vector_set(void *vector, int index, ...);
void vector_clear(void *vector);

extern void *__POINTER_SIZE__;
#define getPointerSize1(TYPE) ((unsigned long)((TYPE)__POINTER_SIZE__ + 1) - (unsigned long)((TYPE)__POINTER_SIZE__))
#define getPointerSize0(TYPE) (sizeof(TYPE))
#define newVector(TYPE, ...)                                                                                                     \
    {                                                                                                                            \
        .info = {.typeinfo = #TYPE, .lengthinfo = #__VA_ARGS__, .size1 = getPointerSize1(TYPE), .size2 = getPointerSize0(TYPE)}, \
        .length = 0,                                                                                                             \
        .data = NULL,                                                                                                            \
        .resize = vector_resize,                                                                                                 \
        .append = vector_append,                                                                                                 \
        .get = vector_get,                                                                                                       \
        .set = vector_set,                                                                                                       \
        .pop = vector_pop,                                                                                                       \
        .insert = vector_insert,                                                                                                 \
        .remove = vector_remove,                                                                                                 \
        .clear = vector_clear,                                                                                                   \
        .type = NOTINIT                                                                                                          \
    }

#endif
